﻿#pragma once

#include <ctime>
#include <functional>
#include <memory>
#include <string>
#include <unordered_map>

namespace kratos {
namespace http {

class HttpRequest;
class HttpResponse;
class HttpCall;

using HttpCallPtr = std::weak_ptr<HttpCall>;
using RequestHandler = std::function<bool(HttpCallPtr, HttpCallPtr, std::uint64_t)>;
using ResponseHandler = std::function<void(HttpCallPtr, std::uint64_t)>;
using HeaderMap = std::unordered_map<std::string, std::string>;

/**
 * HTTP基础接口
 */
class HttpBase {

public:
  virtual ~HttpBase() {}
  /**
   * 发起一次异步HTTP请求，当有HTTP响应返回时调用用户事件完成回调
   *
   * \param host 远程主机地址或域名
   * \param port 远程端口
   * \param uri HTTP URI
   * \param method HTTP请求方法，例如:GET
   * \param headers 用户定义的协议头
   * \param content 用户数据
   * \param timeout 连接超时时间
   * \param user_data 用户数据
   * \param handler 用户事件完成回调
   * \retval true 成功
   * \retval false 失败
   */
  virtual auto do_request_async(const std::string &host, int port,
                                const std::string &uri,
                                const std::string &method,
                                const HeaderMap &headers,
                                const std::string &content, int timeout, std::uint64_t user_data,
                                ResponseHandler handler) -> bool = 0;
  /**
   * 在协程内发起一次同步的HTTP请求
   *
   * \param host 远程主机地址或域名
   * \param port 远程端口
   * \param uri HTTP URI
   * \param method HTTP请求方法，例如:GET
   * \param headers 用户定义的协议头
   * \param content 用户数据
   * \param timeout 连接超时时间
   * \return HTTP响应
   */
  virtual auto do_request_co(const std::string &host, int port,
                             const std::string &uri, const std::string &method,
                             const HeaderMap &headers,
                             const std::string &content, int timeout)
      -> HttpCallPtr = 0;
  /**
   * 发起一个异步的监听器，当有HTTP请求到来时调用用户事件完成回调
   *
   * \param host 远程主机地址或域名
   * \param port 远程端口
   * \param user_data 用户数据
   * \param handler 用户事件完成回调
   * \retval true 成功
   * \retval false 失败
   */
  virtual auto wait_request_async(const std::string &host, int port, std::uint64_t user_data,
                                  RequestHandler handler) -> bool = 0;
  /**
   * 在协程内发起一次同步监听器，等待HTTP请求到来
   *
   * \param host 远程主机地址或域名
   * \param port 远程端口
   * \return HTTP请求
   */
  virtual auto wait_request_co(const std::string &host, int port)
      -> HttpCallPtr = 0;
  /**
   * 逻辑主循环
   *
   * \param ms 当前时间戳，毫秒
   */
  virtual auto update(std::time_t ms) -> void = 0;
};

} // namespace http
} // namespace kratos
